//必须引入的核心
import Recorder from 'recorder-core'
import ClientJs from '@/base/clientjs'
//录制wav格式的用这一句就行
import 'recorder-core/src/engine/wav'
//可选的插件支持项，这个是波形可视化插件
import 'recorder-core/src/extensions/frequency.histogram.view.js'
import 'recorder-core/src/extensions/lib.fft.js'
import {dateFormat} from '@/base/utils'

import {reqH5Voice,reqClientRecord} from './AudioStreamer.js'

import { ElMessage } from 'element-plus';
import {qryConfigByFeature,getHttpVoiceTxt} from '@/base/request/commonReq.js'

import Storage from '@/base/storage'

// 定义录音状态的枚举
const RecordState = {
    INIT: 0,//初始化
    OPEN: 1,//打开录音权限
    START:2,//开始录音
    RECORDING: 3,//正在录音
    END: 4,//结束录音
    ERROR:-1,//录音出错
    NOTAllOW:-2,//用户拒绝了录音权限，或者不支持录音
    NOTOPEN:-3,//录音未打开
};

class RecorderManger{
    constructor(recordCfg,refWave,callBackFn){
        //录音参数
        let param = {
            type:'wav',
            sampleRate:16000,//录音的采样率，越大细节越丰富越细腻
            bitRate:16, //录音的比特率，越大音质越好
        }
        Object.assign(param,recordCfg);
        param.onProcess = (buffers, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd)=>{
            //可实时绘制波形，实时上传（发送）数据
            if(refWave) {
                this.refWave.input(buffers[buffers.length - 1], powerLevel, bufferSampleRate);
            };
        }
        // console.info(param);
        this.qryPermission();//查看语音识别文本的权限
        

        let ua = navigator.userAgent;//浏览器发送给服务器的用户代理标头
        this.isIos = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
       /* if(this.isIos){
            this.recorder = {};
        } else {//走H5自带的语音录入

        }*/
        //创建录音对象
        this.recorder =  Recorder(param);
        this.openRecorder();
        console.log("refWave:" + refWave)
        this.refWave = refWave;//声效插件
        this.websocketUrl = '';//websocket路径
        this.status = RecordState.INIT;
        this.callBackFn = callBackFn;
       
    }
    //查看语音识别接口的权限
    qryPermission(){
        this.protocoleType = Storage.session.get('voice_permission');
        this.websocketUrl = Storage.session.get('websocket_url');
        if(this.protocoleType == void 0 || this.protocoleType == ""){
            qryConfigByFeature('voice_recognition_type','').then(res=>{
                let {retCode,data} = res.data;
                if(retCode == '0'){
                    this.protocoleType = data.voice_flag;
                    this.websocketUrl = data.ws_url;
                } else {
                    //默认走websocket协议
                    this.protocoleType = 'websocket'
                }
            }).catch(error=>{
                //默认走websocket协议
                this.protocoleType = 'websocket'
            }).finally(()=>{
                Storage.session.set('voice_permission',this.protocoleType);
                Storage.session.set('websocket_url',this.websocketUrl);
            })
        }
    }
    //打开录音权限
    openRecorder(){
        this.recorder.open(()=>{
            this.status = RecordState.OPEN;
            if(this.refWave){//创建音频可视化图形绘制对象
                this.refWave = Recorder.FrequencyHistogramView({
                    elem: ".recwave-box",
                    lineCount: 10,
                    position: 0,
                    minHeight: 1,
                    stripeEnable: false,
                    linear: [0, "#fff", 1, "#fff"]
                });
            }
        },(msg,isUserNotAllow)=>{
            this.status = RecordState.NOTAllOW;
            //用户拒绝了录音权限，或者浏览器不支持录音
            ElMessage.warning((isUserNotAllow?"UserNotAllow，":"")+"无法录音:"+msg);

        });
    }

    //客户端返回的Base64转blob
    base64ToBlob(base64) {
        var binary = atob(~base64.indexOf(',')?base64.split(',')[1]:base64);
        var array = [];
        for (var i = 0; i < binary.length; i++) {
            array.push(binary.charCodeAt(i));
        }
        return new Blob([new Uint8Array(array)], {type: 'audio/mpeg'});
    }

    //开始录音
    startRecorder(){
        /*if(this.isIos){//add by qhuang at 20240221  ios终端用原生打开
           //获取苹果终端返回的语音流对象
            window['getIosVoiceCb'] = (res)=>{
                let result = JSON.parse(res);
                let {retCode,retMsg,voiceFile} = result;
                if(retCode == 0 && voiceFile){//客户端返回音频成功 采样率16k的wav格式音频
                    // let callBackFn = this.__proto__.callBackMethod;//配置语音识别成功后的结果
                    this.status = RecordState.END;
                    // console.log("录音成功",blob,localUrl,"时长:"+duration+"ms");
                    let duration = parseInt(result.duration || '1') * 1000;//转换成ms
                    this.voiceResult[this._rid].duration = duration;
                    this.voiceResult[this._rid].blob = this.base64ToBlob(voiceFile);//缓存
                    this.callBackFn(this.voiceResult[this._rid]);
                    this.postToServer(voiceFile,false);//请求服务端识别
                } else {
                    ElMessage('获取语音失败，'+retMsg);
                }
            };
            ClientJs.openVoiceRecord('getIosVoiceCb');
            this.status = RecordState.OPEN;
        } else {

        }*/
        if(!this.recorder){
            this.status = RecordState.NOTOPEN;
            ElMessage("未打开录音");
            return;
        }
        this.recorder.start();
        this._rid = 'rec_' +this.getRandomStr();//生成唯一的ID
        let rid = this._rid;
        this.status = RecordState.START;
        let startTime = dateFormat(new Date(),'MM-dd hh:mm');
        this.voiceResult = {rid:{}};
        this.voiceResult[rid] = {rid:rid,startTime:startTime};
    }
    //生成随机数
    getRandomStr(range=10000){
        let rangeNum = parseInt(range,16);
        return (((1+Math.random())*rangeNum)|0).toString(16).substring(1);  
    }
    //取消语音
    cancelRecorder(){
        if(!this.recorder){ 
            return;
        }
        this.recorder.stop((blob,duration)=>{
            this.status = RecordState.END;
        },(err)=>{
            this.status = RecordState.ERROR;
            console.error("结束录音出错："+err);
        });
    }
    //结束录音
    endRecorder(){
       /* if(this.isIos){//add by qhuang at 20240221  ios终端用原生打开
            return;
        }*/
        if(!this.recorder){
            ElMessage("未打开录音");
            return;
        }
        setTimeout(() => {//延迟2秒关闭录音
            this.recorder.stop((blob,duration)=>{
                //blob就是我们要的录音文件对象，可以上传，或者本地播放
                // this.recBlob = blob;
                //简单利用URL生成本地文件地址，此地址只能本地使用，比如赋值给audio.src进行播放，赋值给a.href然后a.click()进行下载（a需提供download="xxx.mp3"属性）
                // var localUrl = (window.URL||webkitURL).createObjectURL(blob);
                this.status = RecordState.END;
                // console.log("录音成功",blob,localUrl,"时长:"+duration+"ms");
                this.voiceResult[this._rid].duration = duration;
                this.voiceResult[this._rid].blob = blob;//缓存
                this.callBackFn(this.voiceResult[this._rid]);
                this.postToServer(blob,true);//把blob文件上传到服务器
    
            },(err)=>{
                this.status = RecordState.ERROR;
                ElMessage("结束录音出错："+err)
                console.error("结束录音出错："+err);
            });
        }, 2000);
    }

    //blob流转成字符串
    blobToBase64(blob) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result);
            reader.onerror = reject;
            reader.readAsDataURL(blob);
        });
    }
    //解析语音文本，通过websocket实时翻译或者http非实时转译
    async postToServer (recBlob,isBlob) {
        let base64 = recBlob;
        if (isBlob) {//是blob流需要转base64
            base64 = await this.blobToBase64(recBlob);
        }
        if(this.protocoleType == 'http'){
            //请求服务端识别语音流（非实时）
            getHttpVoiceTxt(base64).then((res)=>{
                let {code,msg,result} = res.data;
                let resObj = {
                    code:'-1',
                    voiceTxt:msg||'未能正确识别语音，请尝试调大音量'
                }
                if(code == '0' && result){
                    resObj.code = '0';
                    resObj.voiceTxt = result;
                }
                this.getVoiceResult(resObj);//回调给应用侧
            })
        } else {
            const base64WithoutPrefix = isBlob?base64.split(',')[1]:base64; // 移除"data:image/png;base64,"前缀
            console.info('------reqH5Voice')
            //请求websocket识别语音流
            reqH5Voice(base64WithoutPrefix,this.websocketUrl, this.getVoiceResult.bind(this));
        }
    }   
    //获取语音文本 
    getVoiceResult(resObj){
        console.info('in line 274')
        console.info(resObj)
        let {code,voiceTxt} = resObj; 
        this.voiceResult[this._rid].voiceTxt = voiceTxt; //缓存
        this.voiceResult[this._rid].code = code;
        this.callBackFn(this.voiceResult[this._rid]);
    }
    recPlay(recBlob){
        //本地播放录音试听，可以直接用URL把blob转换成本地播放地址，用audio进行播放
        var localUrl = URL.createObjectURL(recBlob);
        var audio = document.createElement("audio");
        audio.controls = true;
        document.body.appendChild(audio);
        audio.src = localUrl;
        audio.play(); //这样就能播放了
        //释放内存 revokeObjectURL
        setTimeout(function(){ URL.revokeObjectURL(audio.src) },5000);
    }
    
}

export default RecorderManger;